package com.client.clovece;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;

import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JPanel;


public class LocalGame extends JFrame implements MouseListener, ItemListener{
	
	private int numPls;
	
	InfoPanel info;
	GamePanel gp;
	Dimension lgd;
	Configuration conf;
	Dice dice;
	ArrayList<Player> plrs;
	Player activePlayer = null;
	AI ai = new AI(this);
	
	GridBagConstraints c1;
	GridBagConstraints c2;
	
	TileButton activeButton = null;
	
	
	
	public LocalGame(LocalMenu parent, int numpls, String savePath){
		numPls = numpls;
		conf = Configuration.getInstance();
		dice = new Dice(this);
		gp = new GamePanel(this);
		info = new InfoPanel(this, numPls);
		plrs = initPlrs();
		initGui();
		
		Container c = getContentPane();
		c.add(info, c1);
		c.add(gp, c2);
	    setDefaultCloseOperation(EXIT_ON_CLOSE);
	    createBufferStrategy(2);
	    
	    activePlayer = plrs.get(0);
	    nextMove();
		
	}
	
	private void initGui(){
		setTitle("Clovece");
		lgd = new Dimension(540,610);
		c1 = new GridBagConstraints();
		c1.fill = GridBagConstraints.HORIZONTAL;
		c1.gridx = 0;
		c1.gridy = 0;
		c1.gridheight = 5;
		c2 = new GridBagConstraints();
		c2.fill = GridBagConstraints.HORIZONTAL;
		c2.gridx = 0;
		c2.gridy = 6;
		c2.gridheight = 10;
		setSize(lgd);
		setMaximumSize(lgd);
		setLayout(new GridBagLayout());
		setResizable(false);
	    setVisible(true);
	}
	
	private ArrayList<Player> initPlrs(){
			ArrayList<Player> plrs = new ArrayList<Player>();
					
			plrs.add(new Player(true, ButtonStates.PL1BRIGHT));
			plrs.get(0).setTokenStart(0, gp.p1start.get(0).getGridArrId());
			plrs.get(0).setTokenStart(1, gp.p1start.get(1).getGridArrId());
			plrs.get(0).setTokenStart(2, gp.p1start.get(2).getGridArrId());
			plrs.get(0).setTokenStart(3, gp.p1start.get(3).getGridArrId());
			
			plrs.add(new Player(true, ButtonStates.PL2BRIGHT));
			plrs.get(1).setTokenStart(0, gp.p2start.get(0).getGridArrId());
			plrs.get(1).setTokenStart(1, gp.p2start.get(1).getGridArrId());
			plrs.get(1).setTokenStart(2, gp.p2start.get(2).getGridArrId());
			plrs.get(1).setTokenStart(3, gp.p2start.get(3).getGridArrId());
			
			plrs.add(new Player(true, ButtonStates.PL3BRIGHT));
			plrs.get(2).setTokenStart(0, gp.p3start.get(0).getGridArrId());
			plrs.get(2).setTokenStart(1, gp.p3start.get(1).getGridArrId());
			plrs.get(2).setTokenStart(2, gp.p3start.get(2).getGridArrId());
			plrs.get(2).setTokenStart(3, gp.p3start.get(3).getGridArrId());
			
			plrs.add(new Player(true, ButtonStates.PL4BRIGHT));
			plrs.get(3).setTokenStart(0, gp.p4start.get(0).getGridArrId());
			plrs.get(3).setTokenStart(1, gp.p4start.get(1).getGridArrId());
			plrs.get(3).setTokenStart(2, gp.p4start.get(2).getGridArrId());
			plrs.get(3).setTokenStart(3, gp.p4start.get(3).getGridArrId());
			
			return plrs;
	}
	
	public ArrayList<Player> getPlayers(){
		return plrs;
	}
	
	public Player getPlayer(ButtonStates p){
		switch(p){
			case PL1BRIGHT: return plrs.get(0); 
			case PL2BRIGHT: return plrs.get(1);
			case PL3BRIGHT: return plrs.get(2);
			case PL4BRIGHT: return plrs.get(3);
		}
		return null;
	}
	
	public void nextMove(){
		do{//if activeplayer == null
			dice.thrw();
			if(activePlayer.getAttempts()<3 && allHome()){
				info.setActiveIcon(activePlayer.getImg());
				activePlayer.incAttempts();
			}else if(dice.getLastVal() == 6){
			
			}else{
				activePlayer = plrs.get((plrs.indexOf(activePlayer)+1) % numPls);
				info.setActiveIcon(activePlayer.getImg());
				activePlayer.nullAttempts();
				activePlayer.incAttempts();
			}	
		
			info.setDice(dice.getIcon());
			if(activeButton != null){
				activeButton.setIconAndStateBright();
				activeButton = null;
			}
			System.out.println("Na tahu: "+activePlayer.getIndex()+"; Kostka: "+dice.getVal());
			if(!activePlayer.getControl()){
				System.out.println("AI na tahu");
				/*try {
					//paint(this.getGraphics());
					Thread.sleep(500);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}*/
				ai.move(activePlayer, dice.getVal());
			}
		}while(!activePlayer.getControl());
	}
	
	public boolean allHome(){
		for(int i=0; i<4; i++){
			try{
				TileButton myTile = gp.getStartTiles(activePlayer.getId()).get(i);
				if(myTile != null){
					if(!myTile.isTempStateSet()){
						return false;
					}
				}
			}catch (NullPointerException e){
				//System.err.println("Home tile number " + i + " is null. Player: " + activePlayer.getId().toString());
				e.printStackTrace();
			}
		}
		return true;
	}
	
	private boolean canGoHome(int gridPos, int dice){
		int d = activePlayer.getTokenDist(gridPos);
		//nezmenit na > ??
		if(d+dice >= gp.game.size()){
			return true;
		}
		return false;
	}
	
	private boolean findCrossroad(int from, int dice, int player){
		for(int i=1; i<dice; i++){
			if(gp.game.get((from+i)%gp.game.size()).equals(gp.crossroads.get(player)));
		}
		return false;
	}
	
	
	//kick() v poli start zmeni obrazek a v tride player zaznaci
	//novou pozici vyhozene figurky
	public void kick(int from){
		TileButton t = gp.grid.get(from);
		ButtonStates tState = t.getTempState();
		TileButton free = null;
		if(tState == ButtonStates.PL1BRIGHT){
			free = findFreeTileButton(gp.p1start);						
		}else if(tState == ButtonStates.PL2BRIGHT){
			free = findFreeTileButton(gp.p2start);
		}else if(tState == ButtonStates.PL3BRIGHT){
			free = findFreeTileButton(gp.p3start);
		}else if(tState == ButtonStates.PL4BRIGHT){
			free = findFreeTileButton(gp.p4start);
		}
		
		/**TODO
		 * vyhodit nejakou rozumnejsi chybu.
		 * */
		if(free == null){
			System.err.format("Chyba, pole start jsou obsazena.");
			//System.exit(-1);
		}
		free.setTempStateAndIcon(tState);
		getPlayer(tState).setTokenPos(t.getGridArrId(), free.getGridArrId());
		getPlayer(tState).setTokenDist(t.getGridArrId(), 0);
		
	}
	
	
	TileButton findFreeTileButton(ArrayList<TileButton> tButtons){
		for(TileButton b: tButtons){
			if(!b.isTempStateSet()) return b;
		}
		return null;
	}
	
	private void moveTo(TileButton bFrom, TileButton bTo, Player player){
		bTo.setTempStateAndIcon(bFrom.getTempState());
		bTo.setIconAndStateBright();
		player.setTokenPos(bFrom.getGridArrId(), bTo.getGridArrId(), 1);
		bFrom.setIconAndStateDefault();
	}
	
	/**
	 * !TODO Doplnit pohyb z game na obsazene crossroad
	 * */
	//volano z mouseClicked
	//zkusit prepsat... na vstupu bfrom + bto
	//kontrholovat activebutton.tempstate na nesmyslné hodnoty
	public boolean manageMoves(TileButton bTo){
		boolean retval = false;
		Player tmpPlayer = getPlayer(ButtonStates.getOwner(activeButton.getTempState()));
		System.out.println("Metoda managemoves. FROM: " + activeButton.getGridArrId() + " TO: " + bTo.getGridArrId());
		if(ButtonStates.isEmpty(bTo.getTempState()) 
				&& ButtonStates.isGame(bTo.getDefaultState())
				&& ButtonStates.isGame(activeButton.getDefaultState())){
			//pohyb z pole role game na prazdne pole game
			//pokud jsou tlacitka vzdalena o hod, nebo jsou vzdalena o hod -(delka pole - pozice aktivniho tlacitka)
			//a pokud neprekroci krizovatku
			if(activeButton.getRoleArrId() + dice.getVal() == bTo.getRoleArrId()|| dice.getVal()-(gp.game.size()-activeButton.getRoleArrId()) == bTo.getRoleArrId()){
				if(!canGoHome(activeButton.getGridArrId(),dice.getVal())){
					System.out.println(activeButton.getRoleArrId()+" -> "+bTo.getRoleArrId());
					moveTo(activeButton, bTo, activePlayer);
					retval = true;
				}
			}
		}else if(!ButtonStates.isEmpty(bTo.getTempState()) 
				&& ButtonStates.getOwner(bTo.getTempState()) != ButtonStates.getOwner(activeButton.getTempState()) 
				&& ButtonStates.isGame(bTo.getDefaultState())
				&& ButtonStates.isGame(activeButton.getDefaultState())){
			//pohyb z pole game na obsazene game
			if(activeButton.getRoleArrId() + dice.getVal() == bTo.getRoleArrId() || dice.getVal()-(gp.game.size()-activeButton.getRoleArrId()) == bTo.getRoleArrId()){
				if(!canGoHome(activeButton.getGridArrId(),dice.getVal())){
					kick(bTo.getGridArrId());
					moveTo(activeButton, bTo, activePlayer);
					retval = true;
				}
			}
			
		}else if(ButtonStates.isEmpty(bTo.getTempState())
				&& ButtonStates.getOwner(bTo.getDefaultState()) == ButtonStates.getOwner(activeButton.getTempState()) 
				&& ButtonStates.isEnd(bTo.getDefaultState()) 
				&& ButtonStates.isGame(activeButton.getDefaultState())){
			System.out.println("GAME->END");
			int i = gp.getCrossroad(ButtonStates.getOwner(activeButton.getTempState())).getRoleArrId();
			System.out.println("Kliknuto na pole: END " + i);
			//int i = gp.crossroads.get(ButtonStates.getOwner(activeButton.getTempState()).ordinal()-1).getRoleArrId();
			if(i<activeButton.getRoleArrId()){
				i += gp.game.size();
			}
			int j = dice.getVal()-(i-activeButton.getRoleArrId());
			if(j > 0 && bTo.equals(gp.getEndTiles(ButtonStates.getOwner(activeButton.getTempState())).get(j-1))
					 && canGoHome(activeButton.getGridArrId(),dice.getVal())){
				//!kontrolni vypis
				System.out.println("Hodnota j je:"+j);
				bTo.setTempStateAndIcon(ButtonStates.getOwner(activeButton.getTempState()));
				tmpPlayer.setTokenPos(activeButton.getGridArrId(), bTo.getGridArrId());
				activeButton.setIconAndStateDefault();
				retval = true;
			}
		}else if(ButtonStates.isEmpty(bTo.getTempState()) 
				&& ButtonStates.getOwner(bTo.getDefaultState()) == ButtonStates.getOwner(activeButton.getTempState())
				&& ButtonStates.isEnd(bTo.getDefaultState()) 
				&& ButtonStates.isCrossRoad(activeButton.getDefaultState())){
			//Pohyb z crossroad na end
			System.out.println("CROSSROAD->END");
			bTo.setTempStateAndIcon(activeButton.getTempState());
			bTo.setIconAndStateBright();
			tmpPlayer.setTokenPos(activeButton.getGridArrId(), bTo.getGridArrId(), 1);
			activeButton.setIconAndStateDefault();
			retval = true;
			
		}else if(ButtonStates.isEmpty(bTo.getTempState()) 
				&& ButtonStates.isCrossRoad(bTo.getDefaultState()) 
				&& ButtonStates.isStart(activeButton.getDefaultState())){
			//pohyb z pole start na crossroad
			System.out.println("START->CROSSROAD");
			if(dice.getVal() == 6 && gp.crossroads.get(ButtonStates.getOwner(activeButton.getTempState()).ordinal()) == bTo){
				bTo.setTempStateAndIcon(activeButton.getTempState());
				bTo.setIconAndStateBright();
				tmpPlayer.setTokenPos(activeButton.getGridArrId(), bTo.getGridArrId(), 1);
				activeButton.setIconAndStateDefault();
				retval = true;
			}
		}else if(!ButtonStates.isEmpty(bTo.getTempState())
				&& ButtonStates.getOwner(bTo.getTempState()) != ButtonStates.getOwner(activeButton.getTempState())
				&& ButtonStates.isCrossRoad(bTo.getDefaultState()) 
				&& ButtonStates.isStart(activeButton.getDefaultState())){
			//pohyb z pole start na obsazene Crossroad
			if(dice.getVal() == 6 && gp.crossroads.get(ButtonStates.getOwner(activeButton.getTempState()).ordinal()) == bTo){
				System.out.println("START->CROSSROAD KICK");
				kick(bTo.getGridArrId());
				bTo.setTempStateAndIcon(ButtonStates.getOwner(activeButton.getTempState()));
				tmpPlayer.setTokenPos(activeButton.getGridArrId(), bTo.getGridArrId(), 1);
				activeButton.setIconAndStateDefault();
				retval = true;
			}
		}else if(ButtonStates.isEmpty(bTo.getTempState())
				&& ButtonStates.getOwner(bTo.getTempState()) != ButtonStates.getOwner(activeButton.getTempState())
				&& ButtonStates.isCrossRoad(activeButton.getDefaultState())
				&& ButtonStates.isGame(bTo.getDefaultState())){
			//pohyb z pole crossroad na game
			System.out.println("CROSSROAD->GAME");
			bTo.setTempStateAndIcon(activeButton.getTempState());
			bTo.setIconAndStateBright();
			tmpPlayer.setTokenPos(activeButton.getGridArrId(), bTo.getGridArrId(), 1);
			activeButton.setIconAndStateDefault();
			retval = true;
		}else if(!ButtonStates.isEmpty(bTo.getTempState())
				&& ButtonStates.getOwner(bTo.getTempState()) != ButtonStates.getOwner(activeButton.getTempState())
				&& ButtonStates.isCrossRoad(activeButton.getDefaultState())
				&& ButtonStates.isGame(bTo.getDefaultState())){
				//pohyb z pole crossroad na obsazene pole game 
			System.out.println("CROSSROAD->GAME KICK");
			kick(bTo.getGridArrId());
			bTo.setTempStateAndIcon(ButtonStates.getOwner(activeButton.getTempState()));
			tmpPlayer.setTokenPos(activeButton.getGridArrId(), bTo.getGridArrId(), 1);
			activeButton.setIconAndStateDefault();
			retval = true;
		}else if(ButtonStates.isEmpty(bTo.getTempState()) 
				&& ButtonStates.getOwner(bTo.getTempState()) != ButtonStates.getOwner(activeButton.getTempState())
				&& ButtonStates.isGame(activeButton.getDefaultState())
				&& ButtonStates.isCrossRoad(bTo.getDefaultState())){
			//pohyb z game na crossroad
			System.out.println("GAME -> CROSSROAD");
			bTo.setTempStateAndIcon(activeButton.getTempState());
			bTo.setIconAndStateBright();
			tmpPlayer.setTokenPos(activeButton.getGridArrId(), bTo.getGridArrId(), 1);
			activeButton.setIconAndStateDefault();
			retval = true;
		}else if(!ButtonStates.isEmpty(bTo.getTempState())
				&& ButtonStates.getOwner(bTo.getTempState()) != ButtonStates.getOwner(activeButton.getTempState())
				&& ButtonStates.isGame(activeButton.getDefaultState())
				&& ButtonStates.isCrossRoad(bTo.getDefaultState())){
			//pohyb z game na obsazzene crossroad
			System.out.println("GAME->CROSSROAD KICK");
			kick(bTo.getGridArrId());
			bTo.setTempStateAndIcon(ButtonStates.getOwner(activeButton.getTempState()));
			tmpPlayer.setTokenPos(activeButton.getGridArrId(), bTo.getGridArrId(), 1);
			activeButton.setIconAndStateDefault();
		}else if(ButtonStates.isEmpty(bTo.getTempState())
				&& ButtonStates.getOwner(bTo.getDefaultState()) == ButtonStates.getOwner(activeButton.getTempState()) 
				&& ButtonStates.isEnd(bTo.getDefaultState())
				&& ButtonStates.isEnd(activeButton.getDefaultState())){
			//pohyb v home
			System.out.println("END->END");
			int j = gp.getEndTiles(activeButton.getDefaultState()).indexOf(activeButton);
			int k = gp.getEndTiles(bTo.getDefaultState()).indexOf(bTo);
			System.out.println("activeButton has index: " + j + "bTo has index: " + k);
			if(k-j == dice.getVal()){
				bTo.setTempStateAndIcon(activeButton.getTempState());
				tmpPlayer.setTokenPos(activeButton.getGridArrId(), bTo.getGridArrId());
				activeButton.setIconAndStateDefault();
				retval = true;
			}
		}
		//spolecne pro vsechny ukony... vynuceni prekresleni
			bTo.setIconAndStateBright();
			bTo.update(bTo.getGraphics());
			activeButton.update(activeButton.getGraphics());
		return retval;
	}
	
	@Override
	public void mouseClicked(MouseEvent e) {
		Object clicked = e.getSource();
		TileButton b;
		
		if(clicked.equals(info.skipButton)){
			nextMove();
		}
		else if(activePlayer.getControl()){//pokud hraje zivy hrac
			b = (TileButton)clicked;
			//!!!Kontrolni vypis
			System.out.println("Kliknuto na tlacitko: "+b.getGridArrId() + "Role: " + b.getDefaultState() +  " Momentalni vlastnik: " + b.getTempState() + " vystup getOwner:" + ButtonStates.getOwner(b.getTempState()));
			if(activeButton == null) System.out.println("Aktivni je null");
			else System.out.println("Aktivni tlacitko: "+activeButton.getGridArrId() + "Role: " + activeButton.getDefaultState() + " Momentalni vlastnik: " + activeButton.getTempState() + " vystup getOwner: " + ButtonStates.getOwner(activeButton.getTempState()));
			if(activeButton == null){//pokud neni zadne tlacitko aktivni
				if(getPlayer(ButtonStates.getOwner(b.getTempState())) == activePlayer){
					System.out.println("Nastaveno ActiveButton, predtim null");
					b.setIconAndStateShaded();
					activeButton = b;//stane se kliknute aktivnim
					System.out.println("Nove aktivni tlacitko: "+activeButton.getGridArrId() + "Role: " + activeButton.getDefaultState() + " Momentalni vlastnik: " + activeButton.getTempState() + " vystup getOwner: " + ButtonStates.getOwner(activeButton.getTempState())) ;
				}
			}else{//kdyz je nejake tlacitko uz aktivni a id se se shoduji
					if(b == activeButton){//druhe kliknuti na stejne tlacitko zpusobi deaktivaci
						System.out.println("Deaktivace tlacitka.");
						b.setIconAndStateBright();
						activeButton = null;
					}else if(b != activeButton && ButtonStates.getOwner(b.getTempState()) == (ButtonStates.getOwner(activeButton.getTempState()))){
						//kliknuti na tlacitko vlastnene stejnym hracem prenese aktivitu na nove tlacitko
						System.out.println("Zmena aktivniho tlacitka");
						activeButton.setIconAndStateBright();
						b.setIconAndStateShaded();
						activeButton = b;
					}else{
						if(manageMoves(b)){
							activeButton = null;
							nextMove();
						}
					}
			}
			
		}
	}
	


	@Override
	public void mouseEntered(MouseEvent e) {
		// TODO Auto-generated method stub
		
	}



	@Override
	public void mouseExited(MouseEvent e) {
		// TODO Auto-generated method stub
		
	}



	@Override
	public void mousePressed(MouseEvent e) {
		// TODO Auto-generated method stub
		
	}



	@Override
	public void mouseReleased(MouseEvent e) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void itemStateChanged(ItemEvent e) {
		JCheckBox b;
		if(e.getSource().getClass().getName() == "javax.swing.JCheckBox"){
			b = (JCheckBox) e.getSource();
			if(b.equals(info.chx1)){
				getPlayer(ButtonStates.PL1BRIGHT).setControl(!b.isSelected());//AI prebira kontrolu, playerincontrol == false
			}else if(b.equals(info.chx2)){
				getPlayer(ButtonStates.PL2BRIGHT).setControl(!b.isSelected());
			}else if(b.equals(info.chx3)){
				getPlayer(ButtonStates.PL3BRIGHT).setControl(!b.isSelected());
			}else if(b.equals(info.chx4)){
				getPlayer(ButtonStates.PL4BRIGHT).setControl(!b.isSelected());
			}
		}		
	}
	
}
